package org.example.demo01.service;

import org.example.demo01.entity.Dispatch;
import org.example.demo01.entity.Piece;
import org.example.demo01.entity.Process;
import org.example.demo01.repository.DispatchRepository;
import org.example.demo01.repository.PieceRepository;
import org.example.demo01.repository.ProcessRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DispatchService {

    private static final Logger logger = LoggerFactory.getLogger(DispatchService.class);

    private static final DateTimeFormatter TIME_FORMATTER =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private PieceRepository pieceRepository;
    @Autowired
    private DispatchRepository dispatchRepository;
    @Autowired
    private ProcessRepository processRepository;

    @Transactional
    public void schedulePieces() {
        logger.info("Starting to schedule pieces...");
        dispatchRepository.deleteAll();

        List<Piece> pieces = pieceRepository.findAll();
        logger.info("Found {} pieces", pieces.size());

        if (pieces.isEmpty()) {
            logger.warn("No pieces found in the database.");
            return;
        }

        Map<String, List<Piece>> piecesByPid = pieces.stream()
                .collect(Collectors.groupingBy(Piece::getPid));

        int queueNumber = 1;

        for (Map.Entry<String, List<Piece>> entry : piecesByPid.entrySet()) {
            String pid = entry.getKey();
            List<Piece> piecesForPid = entry.getValue();

            List<Piece> sortedPieces = piecesForPid.stream()
                    .sorted(Comparator.comparingInt(p -> getElapsedForProduct(p.getPid())))
                    .collect(Collectors.toList());

            for (Piece piece : sortedPieces) {
                List<Process> processes = processRepository.findByPid(pid);
                for (Process process : processes) {
                    Dispatch dispatch = new Dispatch();
                    dispatch.setId(UUID.randomUUID().toString());
                    dispatch.setPieid(piece.getId());
                    dispatch.setWsid(process.getWsid());
                    dispatch.setQid(String.valueOf(queueNumber));
                    dispatch.setStatus(Dispatch.WAITING);
                    dispatchRepository.save(dispatch);
                }
            }
            queueNumber++;
        }
    }

    private int getElapsedForProduct(String pid) {
        return processRepository.findByPid(pid).stream()
                .mapToInt(p -> Integer.parseInt(p.getElapsed()))
                .min()
                .orElse(1);
    }

    @Transactional
    public String startProcessing(String wsid) {
        List<Dispatch> waitingDispatches = dispatchRepository.findByWsidAndStatusOrderByQidAsc(wsid, Dispatch.WAITING);
        if (waitingDispatches.isEmpty()) {
            throw new RuntimeException("工位" + wsid + "没有可启动的任务");
        }

        if (!dispatchRepository.findByWsidAndStatusIn(wsid,
                Arrays.asList(Dispatch.PROCESSING, Dispatch.PAUSED)).isEmpty()) {
            throw new RuntimeException("工位" + wsid + "已有活跃任务(加工中或已暂停)");
        }

        Dispatch dispatch = waitingDispatches.get(0);
        dispatch.setStatus(Dispatch.PROCESSING);
        dispatch.setStartingtime(LocalDateTime.now().format(TIME_FORMATTER));
        dispatchRepository.save(dispatch);

        return "工位" + wsid + "已启动加工件号: " + dispatch.getPieid();
    }

    @Transactional
    public String pauseProcessing(String wsid) {
        List<Dispatch> paused = dispatchRepository.findByWsidAndStatus(wsid, Dispatch.PAUSED);
        if (!paused.isEmpty()) {
            throw new RuntimeException("工位" + wsid + "已有暂停的任务");
        }

        List<Dispatch> processing = dispatchRepository.findProcessingByWsid(wsid);
        if (processing.isEmpty()) {
            throw new RuntimeException("工位" + wsid + "没有正在加工的任务");
        }

        Dispatch dispatch = processing.get(0);
        dispatch.setStatus(Dispatch.PAUSED);
        // 使用 endtime 字段临时存储暂停时间
        dispatch.setEndtime(LocalDateTime.now().format(TIME_FORMATTER));
        dispatchRepository.save(dispatch);

        return "工位" + wsid + "已暂停加工件号: " + dispatch.getPieid();
    }

    @Transactional
    public String resumeProcessing(String wsid) {
        List<Dispatch> paused = dispatchRepository.findByWsidAndStatus(wsid, Dispatch.PAUSED);
        if (paused.isEmpty()) {
            throw new RuntimeException("工位" + wsid + "没有已暂停的任务");
        }

        Dispatch dispatch = paused.get(0);
        dispatch.setStatus(Dispatch.PROCESSING);
        // 清空临时存储的暂停时间
        dispatch.setEndtime(null);
        dispatchRepository.save(dispatch);

        return "工位" + wsid + "已继续加工件号: " + dispatch.getPieid();
    }

    @Transactional
    public String finishProcessing(String wsid) {
        List<Dispatch> activeTasks = dispatchRepository.findByWsidAndStatusIn(
                wsid,
                Arrays.asList(Dispatch.PROCESSING, Dispatch.PAUSED));

        if (activeTasks.isEmpty()) {
            throw new RuntimeException("工位" + wsid + "没有可完成的任务");
        }

        Dispatch dispatch = activeTasks.get(0);
        dispatch.setStatus(Dispatch.FINISHED);
        dispatch.setEndtime(LocalDateTime.now().format(TIME_FORMATTER));
        dispatchRepository.save(dispatch);

        return scheduleToNextWorkstation(wsid, dispatch);
    }

    private String scheduleToNextWorkstation(String wsid, Dispatch dispatch) {
        Optional<Piece> piece = pieceRepository.findById(dispatch.getPieid());
        if (!piece.isPresent()) {
            return "工位" + wsid + "已完成加工件号: " + dispatch.getPieid();
        }

        String pid = piece.get().getPid();
        List<Process> processes = processRepository.findByPid(pid);
        if (processes.size() <= 1) {
            return "工位" + wsid + "已完成加工件号: " + dispatch.getPieid() + " (无下一工序)";
        }

        Optional<Process> nextProcess = processes.stream()
                .filter(p -> !p.getWsid().equals(wsid))
                .min(Comparator.comparingInt(p -> Integer.parseInt(p.getElapsed())));

        if (nextProcess.isPresent()) {
            Dispatch newDispatch = new Dispatch();
            newDispatch.setId(UUID.randomUUID().toString());
            newDispatch.setPieid(dispatch.getPieid());
            newDispatch.setWsid(nextProcess.get().getWsid());
            newDispatch.setQid(dispatch.getQid());
            newDispatch.setStatus(Dispatch.WAITING);
            dispatchRepository.save(newDispatch);

            return "工位" + wsid + "已完成加工件号: " + dispatch.getPieid() +
                    ", 已调度到工位" + nextProcess.get().getWsid();
        }

        return "工位" + wsid + "已完成加工件号: " + dispatch.getPieid() + " (无下一工序)";
    }

    public String getWorkstationStatus(String wsid) {
        if (!dispatchRepository.findProcessingByWsid(wsid).isEmpty()) {
            return "PROCESSING";
        }
        if (!dispatchRepository.findByWsidAndStatus(wsid, Dispatch.PAUSED).isEmpty()) {
            return "PAUSED";
        }
        if (!dispatchRepository.findByWsidAndStatusOrderByQidAsc(wsid, Dispatch.WAITING).isEmpty()) {
            return "WAITING";
        }
        return "IDLE";
    }
}